using System;
using System.Collections.Generic;
using System.Text;
using CodePlex.Resourceful;
using System.Collections.Specialized;
using System.IO;

namespace CodePlex.SpaceBlock.FS
{

    public enum SortCode
    {
        Name, CreatedDate, SizeBytes, FileType
    }

    public class NirvanixClient : Client
    {
        private readonly bool _useSSL;

        public NirvanixClient(bool useSSL)
            : base(new Uri((useSSL?"https":"http") + "://services.nirvanix.com/"))
        {
            _useSSL = useSSL;
        }

        public bool IsSSL
        {
            get
            {
                return _useSSL;
            }
        }

        


        public ClientResponse Authentication_Login(string appKey, string username, string password)
        {
            NameValuePairs nvp = new NameValuePairs();
            nvp["appKey"] = appKey;
            nvp["userName"] = username;
            nvp["password"] = password;

            return this.GetRepresentation("ws/Authentication/Login.ashx", nvp);
        }


        public ClientResponse IMFS_CreateFolders(string sessionToken, params string[] folderPaths)
        {

            NameValueCollection nvc = new NameValueCollection();
            nvc["sessionToken"] = sessionToken;
           
            foreach(string folderPath in folderPaths) 
            {
                nvc.Add("folderPath",folderPath);
            }

            return this.GetRepresentation("ws/IMFS/CreateFolders.ashx", nvc);
        }

        public ClientResponse IMFS_DeleteFolders(string sessionToken, params string[] folderPaths)
        {

            NameValueCollection nvc = new NameValueCollection();
            nvc["sessionToken"] = sessionToken;

            foreach (string folderPath in folderPaths)
            {
                nvc.Add("folderPath", folderPath);
            }

            return this.GetRepresentation("ws/IMFS/DeleteFolders.ashx", nvc);
        }

        public ClientResponse IMFS_DeleteFiles(string sessionToken, params string[] filePaths)
        {

            NameValueCollection nvc = new NameValueCollection();
            nvc["sessionToken"] = sessionToken;

            foreach (string filePath in filePaths)
            {
                nvc.Add("filePath", filePath);
            }

            return this.GetRepresentation("ws/IMFS/DeleteFiles.ashx", nvc);
        }

        public ClientResponse IMFS_GetDownloadNodes(string sessionToken, params string[] filePaths)
        {
            NameValueCollection nvc = new NameValueCollection();
            nvc["sessionToken"] = sessionToken;

            foreach (string filePath in filePaths)
            {
                nvc.Add("filePath", filePath);
            }

            return this.GetRepresentation("ws/IMFS/GetDownloadNodes.ashx", nvc);
        }



        public ClientResponse IMFS_ListFolder(
            string sessionToken, string folderPath, int pageNumber, int pageSize,  
            SortCode? sortCode, bool? sortDescending, bool? showMetadata, bool? showTags
            )
        {
            NameValuePairs nvp = new NameValuePairs();
            nvp["sessionToken"] = sessionToken;
            nvp["folderPath"] = folderPath;
            nvp["pageNumber"] = pageNumber.ToString();
            nvp["pageSize"] = pageSize.ToString();
            AddOptional(nvp, "sortCode", sortCode);
            AddOptional(nvp, "sortDescending", sortDescending);
            AddOptional(nvp, "showMetadata", showMetadata);
            AddOptional(nvp, "showTags", showTags);

           return this.GetRepresentation("ws/IMFS/ListFolder.ashx", nvp);

        }




        public ClientResponse IMFS_GetStorageNode(string sessionToken, long sizeBytes)
        {
            NameValuePairs nvp = new NameValuePairs();
            nvp["sessionToken"] = sessionToken;
            nvp["sizeBytes"] = sizeBytes.ToString();
            return this.GetRepresentation("ws/IMFS/GetStorageNode.ashx", nvp);
        }


        public ClientResponse IMFS_GetInfo(string sessionToken, string filepath)
        {
            // /ws/IMFS/GetPathInfo.ashx?sessionToken=8da051b0-a60f-4c22-a8e0-d9380edafa6f&itemPath=DirTest/F8.jpg&showMetadata=true&showTags=false&showIsShared=true

            NameValuePairs nvp = new NameValuePairs();
            nvp["sessionToken"] = sessionToken;
            nvp["itemPath"] = filepath;
            nvp["showMetadata"] = true.ToString();
            nvp["showTags"] = false.ToString();
            nvp["showIsShared"] = true.ToString();
            return this.GetRepresentation("ws/IMFS/GetPathInfo.ashx", nvp);

        }





        public ClientResponse Metadata_SetMetadata(string sessionToken, string filepath, NameValuePairs metadata)
        {
       //     /ws/Metadata/SetMetadata.ashx?sessionToken=22b16933-2cd5-40ab-981e-dc9b6cfba06d&path=Folders/subfolder/myfile.txt&metadata=Title:MySong


            NameValueCollection nvc = new NameValueCollection();
            nvc["sessionToken"] = sessionToken;
            nvc["path"] = filepath;
            foreach (KeyValuePair<string, string> kvp in metadata)
            {
                nvc.Add("metadata", kvp.Key + ":" + kvp.Value);
            }
            return this.GetRepresentation("ws/Metadata/SetMetadata.ashx", nvc);

        }


        public ClientResponse Metadata_GetMetadata(string sessionToken, string filepath)
        {
            // /ws/Metadata/GetMetadata.ashx?sessionToken=22b16933-2cd5-40ab-981e-dc9b6cfba06d&sourcePath=Folders/subfolder/myfile.txt

            NameValuePairs nvp = new NameValuePairs();
            nvp["sessionToken"] = sessionToken;
            nvp["path"] = filepath;
            return this.GetRepresentation("ws/Metadata/GetMetadata.ashx", nvp);

        }
        
        









        private void AddOptional(NameValuePairs nvp, string name, object value)
        {
            if (value != null)
            {
                nvp[name] = value.ToString();
            }
        }


        private ClientResponse GetRepresentation(string path, NameValueCollection parameters)
        {
            return this.GetRepresentation(EncodeUrlPath(path, parameters));
        }


        // utils
        private static string EncodeUrlPath(string path, NameValueCollection parameters)
        {
            StringBuilder rt = new StringBuilder();
            rt.Append(path);
            if (parameters.Count > 0)
            {
                rt.Append("?" + EncodeUrlPath(parameters));
            }
            return rt.ToString();
        }

        private static string EncodeUrlPath(NameValueCollection parameters)
        {
            IEnumerable<string> nv = Utils.ConvertAll<KeyValuePair<string, string>, string>(All(parameters), delegate(KeyValuePair<string,string> item)
            {
                return Utils.UrlEncode(item.Key) + "=" + Utils.UrlEncode(item.Value);
            });
            
            return Utils.Join("&", nv);
        }

        private static IEnumerable<KeyValuePair<string,string>> All(NameValueCollection parameters)
        {
            foreach (string key in parameters)
            {
                foreach (string value in parameters.GetValues(key))
                {
                    yield return new KeyValuePair<string, string>(key, value);
                }
            }
        }








    }
}
